Duplicating ALL of a Hierarchy - selectable or not
Here's my solution. The script starts with the selected item and iterates over each child object (recursively to include children of children). If the child object is set to non-selectable, it changes the object to selectable, adds a flag to the object for later, and also adds the object to the current selection.

After duplication of the group, the script iterates through both groups and checks for the flag set earlier. If it finds the flag, it make the object non-selectable again.

import bpy

def CheckSelectStatus(p):
    for c in p.children:
        print(c.name)
        c['hideSelectWasTrue'] = False
        if bpy.data.objects[c.name].hide_select == True:
            bpy.data.objects[c.name].hide_select = False
            c['hideSelectWasTrue'] = True
        c.select = True
        CheckSelectStatus(c)

def RestoreSelectStatus(p):
    for c in p.children:
        if c['hideSelectWasTrue'] == True:
            bpy.data.objects[c.name].hide_select = True
        RestoreSelectStatus(c)

#---------------------------------------------------

#get our selected parent object
p1 = bpy.context.active_object

#iterate through children and make selectable and select them                
CheckSelectStatus(p1)

bpy.ops.object.duplicate()

p2Name = ""

#iterate through selected objects to find duplicated parent object
for obj in bpy.context.selected_objects:
    if obj.parent is None:
        p2Name = obj.name

#iterate through original group and disable selection
RestoreSelectStatus(p1)

#iterate through duplicated group and disable selection       
p2 = bpy.data.objects[p2Name]
RestoreSelectStatus(p2)