What you are trying to do does go against some of the base assumptions liquibase uses: namely that each changeset is unique and not copied across multiple places.
One option would be to add a to the changesets checking whether it has ran or not. For example, using in a changeSet that creates a table. If you use onFail=MARK_RAN, then if the table exists the changeSet will just be marked as ran.
With the extension framework (liquibase.org/extension) there is the option of creating extensions to the changelog parsing classes which can use custom logic to strip out duplicate changeSets before the DatabaseChangeLog object is passed to the validator.
A final option would be to change your changelog naming/organization strategy and have a “changelog-per-feature” approach and each version/client would chose the feature changelogs to include. How well that would work depends on your code and project structure.
Any of those options help?