Basically using a Model Binder written by you and a little Reflection:
public class ClienteModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var tipoString = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Tipo");
        var tipo = Type.GetType(
            (string)tipoString.ConvertTo(typeof(string)), 
            true
        );
        var model = Activator.CreateInstance(type);
        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, tipo);
        return model;
    }
}
At the event Application_Start of your Global.asax.cs, register your Model Binder:
protected void Application_Start()
{
    ModelBinders.Binders.Add(typeof(Cliente), new ClienteModelBinder());
}
In the form or in JSON, you will need to pass a field Tipo so that the Model Binder know what is being passed:
@Html.Hidden("Tipo", Model.GetType())
Or:
{ 'Tipo': 'Pessoa' }
Or you can test something else. For example, if the value passed has defined a CPF or CNPJ, or even a name or a social reason, then it does not need a field Tipo in the form or in the JSON:
var cpf = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Cpf");
if (cpf != null) 
{ 
    /* É Pessoa Física */
    var model = Activator.CreateInstance(typeof(Pessoa));
    bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(Pessoa));
    return model;
}
							
							
						 
thanks, testing here now
– Paulo