Object delete handler
Piotr commented that you could override the Delete operator, as described for a different purpose in this answer: https://blender.stackexchange.com/a/28933/66651 

I am using it to remove derivative objects. It works very well!

class delete_override(bpy.types.Operator):
    """delete objects and their derivatives"""
    bl_idname = "object.delete"
    bl_label = "Object Delete Operator"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        for obj in context.selected_objects:

            # replace with your function:
            my_function(obj)

            bpy.data.objects.remove(obj)
        return {'FINISHED'}


def register():
    bpy.utils.register_class(delete_override)

def unregister():
    bpy.utils.unregister_class(delete_override)