Here is a recursive solution which uses group_by(.key) to decide
which objects to combine.  This could be a little simpler if .children
were more uniform. Sometimes it's absent in the sample data and sometimes it's the unusual value [{}].
def merge:
    def kids:
        map(
            .children
          | if length<1 then empty else .[] end
        )
      | if length<1 then {} else {children:merge} end
    ; 
    def mergegroup:
      {
          title: .[0].title
        , key:   .[0].key
      } + kids
    ;
    if   .==[{}] then .
    else group_by(.key) | map(mergegroup)
    end
;
[ .[] | .[] ] | merge
When run with the -s option as follows
jq -M -s -f filter.jq file1.json file2.json
It produces the following output.
[
  {
    "title": "Title1",
    "key": "12345678",
    "children": [
      {
        "title": "SubTitle2",
        "key": "123456713",
        "children": [
          {}
        ]
      },
      {
        "title": "SubTitle1",
        "key": "12345679",
        "children": [
          {
            "title": "SubSubTitle1",
            "key": "12345610"
          },
          {
            "title": "SubSubTitle2",
            "key": "12345611"
          },
          {
            "title": "DifferentSubSubTitle1",
            "key": "12345612"
          }
        ]
      }
    ]
  }
]
If the ordering of the objects within the .children matters
then an a sort_by can be added to the {children:merge} expression,
e.g. {children:merge|sort_by(.key)}