I had to solve a similar case; I have a lookup relationship between objects - it cannot be a master-detail - and need to make sure all the related objects get deleted when the "parent" is deleted.
The solution I employed was to gather a list of the IDs of the children for all deleted parents (in a bulkified manner) during "before delete" in a trigger. This was stored in a static variable. I then get the details out of the static variable (and clear it, to avoid re-entrant calls to the trigger messing stuff up) before deleting the child objects in "after delete".
I don't know how this will work for record merging, since this isn't relevant in our case, though I dare say the latter could be handled by checking the relationship field (the lookup) on the children to be deleted just before they are deleted...
An alternative solution might be to do something like that described here: https://jenwlee.wordpress.com/2016/10/25/delete-a-record-deleted-its-related-records/
I used a trigger since I needed fine-grained control of related processing as well.