Ok, vendo o código agora entendi o problema. Neste caso realmente não teria muito como fazer porque o model binding não saberia qual das classes instanciar para preencher a propriedade de DadosCadastrais.
Neste caso é quando a gente fala que os modelos que mapeiam as entidades do negócio e do banco ficaram diferentes dos dados que veem da camada de view, no caso um formulário.
A solução mais orientada a objetos que o pessoal vem adotando neste caso é trabalhar com o conceito de ViewModel. A ideia é ter uma classe que é responsável por receber exatamente por receber os dados de acordo com o que tem na tela. Então dado o que tem no seu Cadastro.cshtml
por enquanto, você poderia ter uma ViewModel assim:
public class CadastroClienteViewModel {
public string TipoCliente { get; set; }
public String Nome { get; set; }
public DateTime Nascimento { get; set; }
public string CPF { get; set; }
public string RG { get; set; }
}
Ai em seu método do Controller receber esta classe como parãmetro:
public string NovoCliente(CadastroClienteViewModel cadastro) {
//...
}
Ai dentro dessa classe de ViewModel teria um método CriaCliente
que geraria o modelo de acordo com o que veio da tela. Como existe essa variação de acordo com o que veio do radio button, o método seria mais ou menos assim:
public class CadastroClienteViewModel {
public string TipoCliente { get; set; }
public String Nome { get; set; }
public DateTime Nascimento { get; set; }
public string CPF { get; set; }
public string RG { get; set; }
public Cliente CriaCliente()
{
Cliente cliente = new Cliente();
//preenche propriedades comuns a todos os clientes
if( this.TipoCliente.Equals("PF") ) {
cliente.DadosCadastrais = new PF() {
Nome = this.Nome,
Nascimento = this.Nascimento,
//restante dos dados de PF
};
} else {
cliente.DadosCadastrais = new PJ() {
//restante dos dados de PJ
};
}
return cliente;
}
}
Ai para recuperar o Cliente bastaria chamar o método:
public string NovoCliente(CadastroClienteViewModel cadastro) {
Cliente cliente = cadastro.CriaCliente();
}
Pronto, assim a lógica de saber lidar com o que vem da tela e como traduzir isso para as suas entidades fica isolado dentro de uma única classe que tem apenas essa responsabilidade. E se algum dia a View mudar sua estrutura, seus inputs, etc, você precisaria apenas alterar as propriedades da classe CadastroClienteViewModel
e o método CriaCliente
que o restante se manterá intacto.