You can leverage the ComplexTypeModelBinder to do the actual work, then inject your own logic after it is done.
For example (assuming your custom type is MyCustomType):
public class MyCustomType
{
    public string Foo { get; set; }
}
public class MyCustomTypeModelBinder : IModelBinder
{
    private readonly IDictionary<ModelMetadata, IModelBinder> _propertyBinders;
    public MyCustomTypeModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders)
    {
        this._propertyBinders = propertyBinders;
    }
    public async Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var complexTypeModelBinder = new ComplexTypeModelBinder(this._propertyBinders);
        // call complexTypeModelBinder
        await complexTypeModelBinder.BindModelAsync(bindingContext);
        var modelBound = bindingContext.Model as MyCustomType;
        // do your own magic here
        modelBound.Foo = "custominjected";
    }
}
public class MyCustomTypeModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context.Metadata.ModelType == typeof(MyCustomType))
        {
            var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
            for (var i = 0; i < context.Metadata.Properties.Count; i++)
            {
                var property = context.Metadata.Properties[i];
                propertyBinders.Add(property, context.CreateBinder(property));
            }
            return new MyCustomTypeModelBinder(propertyBinders);
        }
        return null;
    }
}
Then register it:
services.AddMvc(options =>
{
    options.ModelBinderProviders.Insert(0, new MyCustomTypeModelBinderProvider());
});